﻿#include "C3fdPostWidget.h"
#include "ui_C3fdPostWidget.h"
#include "C3fdPdfReport.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QFileInfo>
#include <QFile>
#include <QTextStream>
#include "C3fdPerformCurveDialog.h"

namespace MainWidget
{
	C3fdPostWidget::C3fdPostWidget(QWidget *parent)
		: QWidget(parent), m_Ui(new Ui::C3fdPostWidget)
	{
		m_Ui->setupUi(this);
		m_Ui->dsb_Height->setToolTip(tr("Range: [0.1%, 99.9%]"));
		m_Ui->dsb_Height->setValue(50.0);
		m_Project = Common::C3fdProject::instance();

		m_Ui->lw_WorkingConditions->setIconSize({ 16, 16 });
		connect(&m_Process, SIGNAL(readyReadStandardOutput()), this, SLOT(readProcessOutput()));
		connect(&m_Process, SIGNAL(readyReadStandardError()), this, SLOT(readAllStandardErrorSlot()));
		connect(&m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
		initWorkingConditionsList();
	}

	C3fdPostWidget::~C3fdPostWidget()
	{
		delete m_Ui;
	}

	void C3fdPostWidget::reTranslate()
	{
		m_Ui->retranslateUi(this);
	}

	void C3fdPostWidget::initWorkingConditionsList()
	{
		if (m_Project == nullptr)
		{
			return;
		}
		auto* currentCase = m_Project->getCurrentCase();
		m_Ui->lw_WorkingConditions->clear();
		if (currentCase == nullptr)
		{
			return;
		}
		auto wcs = currentCase->getWorkConditions();
		// 工况排序
		QMap<int, QString> newWcs = {};
		for (auto k : wcs.keys()) {
			newWcs.insert(wcs.value(k)->getOrder(), k);
		}

		for (auto k : newWcs.keys())
		{
			QString path = currentCase->getWorkDir() + m_Project->getWorkingConditionDirName() + QDir::separator() + newWcs.value(k) + QDir::separator() + m_Project->getSolverOutputDirName();
			QDir output(path);
			if (output.isEmpty())
			{
				continue;
			}
			auto *item = new QTreeWidgetItem(m_Ui->lw_WorkingConditions);
			item->setText(0, newWcs.value(k));
			item->setIcon(0, QIcon(":/QUI/icon/c3fd_post.png"));
			m_Ui->lw_WorkingConditions->addTopLevelItem(item);
		}
	}

	void C3fdPostWidget::on_dsb_Height_editingFinished()
	{
		auto value = m_Ui->dsb_Height->value();
		if (value < 0.1 || value > 99.9)
		{
			QMessageBox::critical(this, tr("Error Info"), tr("Range: [0.1%, 99.9%]"));
			m_Ui->dsb_Height->setValue(50);
		}
	}

	void C3fdPostWidget::on_pb_PerformCurve_clicked()
	{
		if (m_PerformCurveDialog == nullptr)
		{
			m_PerformCurveDialog = new C3fdPerformCurveDialog(this);
			connect(m_PerformCurveDialog, SIGNAL(plotPerformCurveSig(QStringList)), this, SLOT(plotPerformCurveSlot(QStringList)));
		}
		QStringList items{};
		for (int i = 0; i < m_Ui->lw_WorkingConditions->topLevelItemCount(); ++i)
		{
			items << m_Ui->lw_WorkingConditions->topLevelItem(i)->text(0).simplified();
		}
		m_PerformCurveDialog->setItems(items);
		m_PerformCurveDialog->show();
	}

	void C3fdPostWidget::on_pb_Post_clicked()
	{
		auto items = m_Ui->lw_WorkingConditions->selectedItems();
		if (items.size() != 1)
		{
			QMessageBox::critical(this, tr("Error Info"), tr("Please select only one working condition!"));
			return;
		}

		auto workingDir = m_Project->getCurrentProjectDir() + m_Project->getWorkingConditionDirName() + QDir::separator() + items.at(0)->text(0);

		if (!QFile::exists(workingDir))
		{
			QMessageBox::critical(this, tr("Error Info"), tr("Missing condition folder!"));
			return;
		}

		for (int i = 1; i < 6; i++)
		{
			QFile file(QString(workingDir + QDir::separator() + "POST_%1.dat").arg(i));
			if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
			{
				QTextStream s(&file);
				s << "1" << endl;
				s.flush();
				file.close();
			}
			else
			{
				QMessageBox::critical(this, tr("Error Info"), tr("Failed to create file!"));
				return;
			}
		}

		auto value = m_Ui->dsb_Height->value();
		if (value < 0.1 || value > 99.9)
		{
			QMessageBox::critical(this, tr("Error Info"), tr("Range: [0.1%, 99.9%]"));
			m_Ui->dsb_Height->setValue(50);
			return;
		}

		QFile post3(workingDir + QDir::separator() + "POST_3.dat");
		if (post3.open(QIODevice::Text | QIODevice::Append))
		{
			QTextStream s(&post3);
			s << QString("%1").arg(value / 100.00) << endl;
			s << "0" << endl;
			s.flush();
			post3.close();
		}
		else
		{
			QMessageBox::critical(this, tr("Error Info"), tr("Failed to create file!"));
			return;
		}

		QFile batFile(workingDir + QDir::separator() + "POST.bat");
		if (batFile.open(QIODevice::Text | QIODevice::WriteOnly | QIODevice::Truncate))
		{
			QTextStream s(&batFile);
			QString postPath = m_Project->getPostExeFileDir();
			for (int i = 1; i < 6; i++)
			{
				s << postPath << "POST_" << i << ".exe< " << workingDir << QDir::separator() << "POST_" << i << ".dat" << endl;
			}
			s << "echo \"Post Finished!\"" << endl;
			s.flush();
			batFile.close();
		}
		else
		{
			QMessageBox::critical(this, tr("Error Info"), tr("Failed to create file!"));
			return;
		}

		m_Process.setProgram(workingDir + QDir::separator() + "POST.bat");
		m_Process.setWorkingDirectory(workingDir);
		m_Process.start();
	}

	void C3fdPostWidget::processFinished(int, QProcess::ExitStatus exitStatus)
	{
		switch (exitStatus)
		{
		case QProcess::NormalExit:
		{
			QStringList files{}, types;

			auto items = m_Ui->lw_WorkingConditions->selectedItems();
			if (items.size() > 1)
			{
				return;
			}
			/*int order = m_Ui->lw_WorkingConditions->currentRow() + 1;
			QString orderStr = "";
			if (order < 1)
			{
				return;
			}
			else if (order < 10)
			{
				orderStr = QString("00%1").arg(order);
			}
			else if (order < 100)
			{
				orderStr = QString("0%1").arg(order);
			}
			else
			{
				orderStr = QString("%1").arg(order);
			}*/
			auto outputPath = m_Project->getCurrentProjectDir() + m_Project->getWorkingConditionDirName() + QDir::separator() + items.at(0)->text(0) + QDir::separator() + m_Project->getSolverOutputDirName() + QDir::separator();

			auto value = m_Ui->dsb_Height->value();
			if (value < 0.1 || value > 99.9)
			{
				QMessageBox::critical(this, tr("Error Info"), tr("Range: [0.1%, 99.9%]"));
				m_Ui->dsb_Height->setValue(50);
				return;
			}

			int height = (int)(value * 10);
			QString heightStr = "";
			if (height < 1)
			{
				return;
			}
			else if (height < 10)
			{
				heightStr = QString("00%1").arg(height);
			}
			else if (height < 100)
			{
				heightStr = QString("0%1").arg(height);
			}
			else
			{
				heightStr = QString("%1").arg(height);
			}
			auto bldsfparam = QString("%1bldsfparam001.plt").arg(outputPath);
			auto vs2ave = QString("%1vs2ave001.plt").arg(outputPath);
			auto bldspr = QString("%1bldspr001-R%2.dat").arg(outputPath).arg(heightStr);
			auto s1flow = QString("%1s1flow001-R%2.plt").arg(outputPath).arg(heightStr);

			if (!QFile::exists(bldsfparam))
			{
				QMessageBox::critical(this, tr("Error Info"), QString(tr("File Not Found: %1!")).arg(bldsfparam));
				return;
			}

			if (!QFile::exists(vs2ave))
			{
				QMessageBox::critical(this, tr("Error Info"), QString(tr("File Not Found: %1!")).arg(vs2ave));
				return;
			}

			if (!QFile::exists(bldspr))
			{
				QMessageBox::critical(this, tr("Error Info"), QString(tr("File Not Found: %1!")).arg(bldspr));
				return;
			}

			if (!QFile::exists(s1flow))
			{
				QMessageBox::critical(this, tr("Error Info"), QString(tr("File Not Found: %1!")).arg(s1flow));
				return;
			}

			files << bldsfparam << vs2ave << bldspr << s1flow;
			types << "vtk"
				<< "vtk"
				<< "qwt"
				<< "vtk";
			emit renderPostDataSig(files, types);
		}
		break;
		case QProcess::CrashExit:
			QMessageBox::critical(this, tr("Error Info"), tr("Post Crashed!"));
			break;
		default:
			QMessageBox::information(this, tr("Information"), tr("Post Stopped!"));
			break;
		}
	}

	void C3fdPostWidget::readProcessOutput()
	{
		QString outputBuffer = QString::fromLocal8Bit(m_Process.readAll());
		emit sendMessage(outputBuffer);
	}

	void C3fdPostWidget::readAllStandardErrorSlot()
	{
		QString outputBuffer = QString::fromLocal8Bit(m_Process.readAllStandardError());
		emit sendMessage(outputBuffer);
	}

	void C3fdPostWidget::on_pb_SaveImage_clicked()
	{
		auto items = m_Ui->lw_WorkingConditions->selectedItems();
		if (items.size() != 1)
		{
			QMessageBox::critical(this, tr("Error Info"), tr("No working condition selected!"));
			return;
		}
		auto wcName = items.at(0)->text(0).simplified();

		QString folder = QFileDialog::getExistingDirectory(this, tr("Select a folder"));
		if (folder.isNull() || folder.isEmpty())
		{
			return;
		}
		auto height = (int)(m_Ui->dsb_Height->value() * 10);
		emit saveImageSig(folder, wcName, height);
	}

	void C3fdPostWidget::plotPerformCurveSlot(QStringList wcs)
	{
		if (wcs.size() < 1)
		{
			return;
		}

		QList<QList<double>> totalData = {};
		QList<QList<double>> perStageData = {};
		for (auto wc : wcs)
		{
			QFile charactFile(m_Project->getCurrentProjectDir() + m_Project->getWorkingConditionDirName() + QDir::separator() + wc + QDir::separator() + m_Project->getSolverOutputDirName() + QDir::separator() + "charact.dat");
			if (!charactFile.open(QIODevice::ReadOnly | QIODevice::Text))
			{
				return;
			}
			QTextStream charact(&charactFile);
			// 跳过标题
			charact.readLine();
			QString line = charact.readLine();
			while (!line.isNull())
			{
				auto data = line.split(" ", QString::SplitBehavior::SkipEmptyParts);
				if (data.size() != 6)
				{
					return;
				}
				bool ok1, ok2, ok3;
				// 进口流量
				auto fmassi = data.at(0).toDouble(&ok1);
				// 压比
				auto rtp = data.at(2).toDouble(&ok2);
				// 效率
				auto effis = data.at(3).toDouble(&ok3);
				if (ok1 && ok2 && ok3)
				{
					totalData.push_back({ fmassi, rtp, effis });
				}
				line = charact.readLine();
			}
			charactFile.close();

			QFile charPerStgFile(m_Project->getCurrentProjectDir() + m_Project->getWorkingConditionDirName() + QDir::separator() + wc + QDir::separator() + m_Project->getSolverOutputDirName() + QDir::separator() + "char-per-stg.dat");
			if (!charPerStgFile.open(QIODevice::ReadOnly | QIODevice::Text))
			{
				return;
			}
			QTextStream charPerStg(&charPerStgFile);
			// 跳过标题
			charPerStg.readLine();
			line = charPerStg.readLine();
			while (!line.isNull())
			{
				auto data = line.split(" ", QString::SplitBehavior::SkipEmptyParts);
				if (data.size() != 4)
				{
					return;
				}
				bool ok1, ok2, ok3;
				// 进口流量
				auto fmCorrect01 = data.at(0).toDouble(&ok1);
				// 压比
				auto rtpStage01 = data.at(2).toDouble(&ok2);
				// 效率
				auto effisStage01 = data.at(3).toDouble(&ok3);
				if (ok1 && ok2 && ok3)
				{
					perStageData.push_back({ fmCorrect01, rtpStage01, effisStage01 });
				}
				line = charact.readLine();
			}
			charPerStgFile.close();
		}

		emit plotPerformCurveSig(totalData, perStageData);
	}

	void C3fdPostWidget::on_pb_GenerateReport_clicked()
	{
		if (m_Project == nullptr)
		{
			return;
		}
		auto *currentCase = m_Project->getCurrentCase();
		if (currentCase == nullptr)
		{
			return;
		}
		auto *data = currentCase->getReportData();
		if (data == nullptr)
		{
			return;
		}
		QString reportFile = QFileDialog::getSaveFileName(this, tr("Save Report"), "", tr("PDF Report (*.pdf)"));
		if (reportFile.isNull() || reportFile.isEmpty())
		{
			return;
		}

		C3fdPdfReport report(reportFile);
		report.generate();
	}

}
